﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using My.Framework.AspNetCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace My.Framework
{
	public class StartupFilter : IStartupFilter
	{
		/// <summary>
		/// 配置中间件
		/// </summary>
		/// <param name="next"></param>
		/// <returns></returns>
		public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
		{
			return async app =>
			{
				// 设置响应报文头信息
				app.Use(async (context, next) =>
				{
					// 执行下一个中间件
					await next.Invoke();

					// 解决刷新 Token 时间和 Token 时间相近问题
					if (!context.Response.HasStarted
						&& context.Response.StatusCode == StatusCodes.Status401Unauthorized
						&& context.Response.Headers.ContainsKey("access-token")
						&& context.Response.Headers.ContainsKey("x-access-token"))
					{
						context.Response.StatusCode = StatusCodes.Status403Forbidden;
					}

				});

				await StartFrameworkAsync(app);
				// 调用启动层的 Startup
				next(app);
			};

		}

		/// <summary>
		/// 开始启动 framework 
		/// </summary>
		/// <param name="app"></param>
		/// <returns></returns>
		public async Task StartFrameworkAsync(IApplicationBuilder app)
		{
			var hostApplicationLifetime = App.ServiceProvider.GetService<IHostApplicationLifetime>();

			if (hostApplicationLifetime == null) return;

			// 启动
			hostApplicationLifetime.ApplicationStarted.Register(() =>
			{
				foreach (var item in App._startups)
				{
					item?.ApplicationStarted(App._host);
				}
			});

			// 停止中
			hostApplicationLifetime.ApplicationStopping.Register(() =>
			{
				foreach (var item in App._startups)
				{
					item?.ApplicationStopping(App._host);
				}
			});

			// 已停止
			hostApplicationLifetime.ApplicationStopped.Register(() =>
			{
				foreach (var item in App._startups)
				{
					item?.ApplicationStopped(App._host);
				}
			});

			App._httpContextAccessor = App.ServiceProvider.GetService<IHttpContextAccessor>();

			foreach (var item in App._startups)
			{
				item?.Configure(App._host);
			}
		}
	}
}
